<?php

/**
 * This file is part of the Codizer package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright   Copyright (c) 2010 Advisa (http://www.advisa.fr)
 * @author      Codizer Core Team <team@codizer.org>
 * @package     Codizer
 */

abstract class f_core_Action
{
	private $view;
	private $model;
	private $cacheContent;
	
	/**
	 * Default executed method by main controller
	 */
	abstract public function execute();
	
	/**
	 * Get the current request
	 *
	 * @return f_core_Request
	 */
	public function getRequest()
	{
		return f_core_Request::getInstance();
	}
	
	/**
	 * Get a request parameter
	 * 
	 * @param $name
	 * @param $defaultValue
	 * @return mixed
	 */
	public function getRequestParameter($name, $defaultValue = null)
	{
		return $this->getRequest()->getParameter($name, $defaultValue);
	}
	
	/**
	 * Return a posted form values
	 * 
	 * @param string $formName
	 * @return array
	 */
	public function getFormValues($formName)
	{
		$formValues = $this->getRequest()->getParameterValues($formName);
		
		if(!is_null($formValues))
		{
			foreach($formValues as $key => $formValue)
			{
                            if(is_array($formValue))
                            {
                                if(!is_array(end($formValue)))
                                {
                                    //@TODO: recursive strippslashes to avoid transformation of array of array into string
                                    $formValue = array_map('stripslashes', $formValue);
                                }
                                $formValues[$key] = $formValue;
                            }
                            else
                            {
                                $formValues[$key] = stripslashes($formValue);
                            }
			
			}
		}
		
		return $formValues;
	}

	/**
	 * Get current main context or a specific one
	 *
	 * @param string $contextName
	 * @return f_core_Context|mixed
	 */
	public function updateContext($contextName, $contextValue)
	{
	    f_core_Context::getInstance()->setContext($contextName, $contextValue);
	}
	
	/**
	 * Get current main context or a specific one
	 * 
	 * @param string $contextName
	 * @return f_core_Context|mixed
	 */
	public function getContext($contextName = null)
	{
		if(is_null($contextName))
		{
			return f_core_Context::getInstance();			
		}
		return f_core_Context::getInstance()->getContext($contextName);
	}
	
	/**
	 * Begin a i18n session
	 * @param string $lang
	 * @return f_core_Context
	 */
	public function beginI18nWork($lang)
	{
		return $this->getContext()->beginI18nWork($lang);
	}
	
	/**
	 * End a i18n session
	 * @param string $lang
	 * @return f_core_Context
	 */	
	public function endI18nWork()
	{
		return $this->getContext()->endI18nWork();
	}

	/**
	 * Begin a i18n session
	 * @param string $lang
	 * @return f_core_Context
	 */
	public function beginBackSession($displayLang = null)
	{
		return $this->getContext()->beginBackSession($displayLang);
	}

	/**
	 * End a i18n session
	 * @param string $lang
	 * @return f_core_Context
	 */
	public function endBackSession()
	{
		return $this->getContext()->endBackSession();
	}

    public function setDisplayLang($displayLang)
	{
		return $this->getContext()->setDisplayLang($displayLang);
	}

	public function getDisplayLang()
	{
		return $this->getContext()->getDisplayLang();
	}

    public function getCultureLabel($culture = null)
    {
        if(is_null($culture)) $culture = $this->getDisplayLang();
        return f_locale_Manager::getCultureLabel($culture);
    }

	/**
	 * Get the current context lang
	 *
	 * @return string
	 */
	public function getContextLang()
	{
		return $this->getContext()->getLang();
	}	
	
	/**
	 * Get the current context
	 *
	 * @return f_context_Block
	 */
	public function getBlockContext()
	{
		return f_context_Block::getInstance();
	}	
	
	/**
	 * Get the current block parameter
	 *
	 * @param string $key
	 * @param mixed $defaultValue
	 * @return mixed
	 */
	public function getBlockParameter($key, $defaultValue = null)
	{
		return f_context_Block::getInstance()->getParameter($key, $defaultValue);
	}
	
	/**
	 * Get the current session instance
	 *
	 * @return f_core_Session
	 */
	public function getSession()
	{
		return f_core_Session::getInstance();
	}
	
	/**
	 * Get the current user context
	 *
	 * @return f_context_User
	 */	
	public function getUserContext($context = "")
	{
		return f_context_User::getInstance($context);
	}
	
	/**
	 * Get the current user setted in user context
	 *
	 * @return mixed
	 */
	public function getUser($context = "")
	{
		return f_context_User::getInstance($context)->getUser();
	}
	
	/**
	 * Check if the current user has the given right
	 *
	 * @param string $ruleName
	 * @return boolean
	 */
	public function userHasRight($ruleName)
	{
		return $this->getUserContext()->hasRight($ruleName);
	}
	
	/**
	 * Get the current rights instance
	 *
	 * @return f_core_Controller
	 */	
	public function getController()
	{
		return f_core_Controller::getInstance();
	}
	
	/**
	 * Get the document provider
	 *
	 * @return f_document_Provider
	 */
	public function getDocumentProvider()
	{
		return f_document_Provider::getInstance();
	}

    /**
     * Create a new document
     * 
     * @param string $model
     * @return f_document_baseDocument
     */
    public function createNewDocument($model)
    {
        return $this->getDocumentProvider()->createNewDocument($model);
    }

    /**
     * Get a document by his unique Id
     *
     * @param string $model
     * @return f_document_baseDocument
     */
    public function getDocumentByUniqueId($uid, $lang)
    {
        return $this->getDocumentProvider()->getByUniqueId($uid, $lang);
    }
	
	/**
	 * Set the view
	 *
	 * @param string $value
	 * @return f_core_Action
	 */
	public function setView($value)
	{
		$this->view = $value;
		return $this;
	}
	
	/**
	 * @return string
	 */
	public function getView()
	{
		return $this->view;
	}
	
	/**
	 * Add a variable to the model
	 * 
	 * @param string $key
	 * @param mixed $value
	 * @return f_core_Action
	 */
	public function addToModel($key, $value)
	{
		$this->model[$key] = $value;
		return $this;
	}
	
	/**
	 * @param mixed $value
	 * @return f_core_Action
	 */
	public function setModel($value)
	{
		$this->model = $value;
		return $this;
	}
	
	/**
	 * @return mixed
	 */
	public function getModel($key = null)
	{
		if(is_null($key))
		{
			return $this->model;
		}
		else
		{
			if(isset($this->model[$key]))
			{
				return $this->model[$key];
			}			
		}
		
		return null;
	}
	
	/**
	 * Get logger system
	 *
	 * @return f_logs_Logger
	 */
	public function getLogger()
	{
		return f_logs_Logger::getInstance();
	}
	
	/**
	 * Get locale from database
	 * Can use some template values
	 *
	 * @return string
	 */	
	public function getLocale($key, $lang = null, $values = null, $default = null)
	{
		return f_locale_Manager::getLocale($key, $lang, $values, $default);
	}

	/**
	 * Return view module name
	 * @return string
	 */
	public function getModuleName()
	{
	   $reflection = new ReflectionObject($this);
	   $vars = explode("_", $reflection->getName());
	   return $vars[1];
	}
	
	/**************************************************************** CACHE METHODS ***********************/
	
	/**
	 * Put datas in a cache file
	 *
	 * @param string $key
	 * @param mixed $datas
	 * @param integer $timeOut
	 * @return boolean
	 */
	public function putInCache($key, $datas, $timeOut = null)
	{
		return f_core_Cache::getInstance()->putInCache($key, $datas, $timeOut);
	}
	
	/**
	 * Check if there is a cache file with the given key
	 *
	 * @param string $key
	 * @return boolean
	 */
	public function hasCache($key)
	{
		return f_core_Cache::getInstance()->hasCache($key);
	}
	
	/**
	 * Get cache file content if valid
	 *
	 * @param string $key
	 * @param mixed $defaultValue
	 * @return mixed
	 */
	public function getCacheContent($key, $defaultValue = null)
	{
		return f_core_Cache::getInstance()->getCacheContent($key, $defaultValue);
	}
	
	/**
	 * Check if the given template from the current module is cached or not
	 *
	 * @param string $templateName
	 * @param string|array $discriminator
	 * @return boolean
	 */
	public function isTemplateCached($templateName, $discriminator = null, $cacheGroup = null)
	{
		$reflection = new ReflectionObject($this);  
   
		list($module, $moduleName) = explode("_", $reflection->name);

		$templateEngine = f_template_Template::getInstance();
		
		$templateEngine->setModuleTemplate($moduleName, $templateName);

		if(!is_null($discriminator))
		{
			if(!is_array($discriminator))
			{
				$discriminator = array($discriminator);
			}
	
			foreach($discriminator as $disc)
			{
				$templateEngine->addCacheDiscriminator($disc);
			}
		}

        $templateEngine->setCacheGroup($cacheGroup);

		if($templateEngine->is_cached($templateEngine->getTemplate(), $templateEngine->getDiscriminator()))
		{			        
			$this->cacheContent['templateName'] = $templateEngine->getTemplate();
			$this->cacheContent['content'] = $templateEngine->fetch($templateEngine->getTemplate(), $templateEngine->getDiscriminator());
			$this->cacheContent['discriminator'] =  $templateEngine->getDiscriminator();
			return true;
		}
		
		return false;
	}		
	
	/**
	 * Retrieve the cache content
	 *
	 * @return string
	 */
	public function getTemplateCacheContent()
	{
		$config = f_loader_Config::getInstance()->getParameters("default");

		$content = "";

		if($config['loggingLevel'] == "DEBUG")
		{
		   list($prefix, $suffix) = explode("/modules", $this->cacheContent['templateName']);
		   $vars = explode("/", $prefix);
		   $tplPath = end($vars)."/modules".$suffix;
		   $content .= "\r\n<!-- START - ".$tplPath."-->\r\n";
		}
		f_logs_Logger::getInstance()->templateLog("Load from cache : ".$this->cacheContent['templateName']." | ".$this->cacheContent['discriminator']);
		$content .= $this->cacheContent['content'];

		if($config['loggingLevel'] == "DEBUG")
		{
		     $content .= "\r\n<!-- END - ".$tplPath."-->\r\n";
		}

		return $content;
	}
	
	/**
	 * Launch an action by her className and retrieve the result
	 *
	 * @param string $actionClassName
	 * @return mixed
	 */	
	public function launchActionByClassName($actionClassName)
	{
		// Split $actionClassName to get module and action values
		$tmp = explode("_", $actionClassName);
		
		if(count($tmp) != 4)
		{
			throw new Exception("bad extends value");
		}
		
		$moduleName = $tmp[1];
		$actionName = str_replace("Action","",$tmp[3]);

		return $this->launchAction($moduleName, $actionName);
	}
	
	/**
	 * Launch an action and retrieve the result
	 *
	 * @param string $moduleName
	 * @param string $actionName
	 * @return mixed
	 */
	public function launchAction($moduleName, $actionName)
	{
		return f_core_Controller::getInstance()->setModule($moduleName)->setAction($actionName)->dispatch();
	}
	
	/**
	 * Log to FirePHP extension
	 *
	 * @param mixed $logObject
	 * @param string $logName
	 */
	public function fireLog($logObject, $logName = null)
	{
		$firePHPLogger = f_logs_Logger::getInstance()->getFirePHPLogger();
		
		if(!is_null($firePHPLogger))
		{
			$firePHPLogger->log($logObject, $logName);
		}
	}
	
	/**
	 * Log to FirePHP extension
	 *
	 * @param mixed $logObject
	 * @param string $logName
	 */	
	public function fireInfo($logObject, $logName = null)
	{
		$firePHPLogger = f_logs_Logger::getInstance()->getFirePHPLogger();
		
		if(!is_null($firePHPLogger))
		{
			$firePHPLogger->info($logObject, $logName);
		}
	}
	
	/**
	 * Log to FirePHP extension
	 *
	 * @param mixed $logObject
	 * @param string $logName
	 */	
	public function fireError($logObject, $logName = null)
	{
		$firePHPLogger = f_logs_Logger::getInstance()->getFirePHPLogger();
		
		if(!is_null($firePHPLogger))
		{
			$firePHPLogger->error($logObject, $logName);
		}
	}
	
	/**
	 * Log to FirePHP extension
	 *
	 * @param mixed $logObject
	 * @param string $logName
	 */	
	public function fireWarn($logObject, $logName = null)
	{
		$firePHPLogger = f_logs_Logger::getInstance()->getFirePHPLogger();
		
		if(!is_null($firePHPLogger))
		{
			$firePHPLogger->info($logObject, $logName);
		}
	}	
}